package multithread.CountDown;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 可以为你的下次面试准备以下一些CountDownLatch相关的问题：
 *
 * 解释一下CountDownLatch概念?
 * CountDownLatch 和CyclicBarrier的不同之处?
 * 给出一些CountDownLatch使用的例子?
 *  CountDownLatch 类中主要的方法?
 *
 * Created by xi on 2018/7/15.
 * 测试主线程等待子线程都执行完毕
 * 如果要在主线程等待所有子线程完成后，还要执行其它操作（比如：结果合并）.
 * 可以用join()方法来等待所有子线程完成后，才继续执行。如
 * Thread.join();
 *   当我们调用某个线程的这个方法时，这个方法会挂起调用线程，直到被调用线程结束执行，调用线程才会继续执行。
 *
 *
 *
 */
public class CountDownLatchTestMainThreadWait {
    private static CountDownLatch sCountDownLatch = null;
    private static final int THREAD_NUMBER = 3;

    /**
     * 主线程也会等待三个子线程完成,join
     */
    private static void method2(){
        List<Thread> lists = new ArrayList<Thread>();
        for(int i=0; i<5; i++){
            Thread thread = new Thread(new ConsumeRunnable("子线程" + (i)));
            lists.add(thread);
            thread.start();
        }
        System.out.println("主线程阻塞,等待所有子线程执行完成");
        for(Thread thread : lists){
            // 如果注释掉thread.join(),启动后 main线程 与 所有子线程 thread并发工作,并不会等待子线程完成后再执行
            try {
                thread.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("所有线程执行完成!");
    }


    /**
     * @param args
     */
    public static void main(String[] args) {
        sCountDownLatch = new CountDownLatch(THREAD_NUMBER);
        //线程池
        ExecutorService fixedThreadPool = Executors
                .newFixedThreadPool(THREAD_NUMBER);
        //执行线程
        fixedThreadPool.execute(new ConsumeRunnable("one"));
        fixedThreadPool.execute(new ConsumeRunnable("two"));
        fixedThreadPool.execute(new ConsumeRunnable("three"));
       // System.out.println("等待3个子线程执行完毕...");
        try {
            sCountDownLatch.await();//count不为0，主线程等待
            System.out.println("3个子线程已经执行完毕，继续执行主线程");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private static class ConsumeRunnable implements Runnable {
        private String mName;

        public ConsumeRunnable(String name) {
            this.mName = name;
        }
        public void run() {
            System.out.println("子线程" + mName + "正在执行");
            try {
                System.out.println("子线程" + mName + "，a");
                sCountDownLatch.countDown();
                System.out.println("子线程" + mName + "，b");
                Thread.sleep(1000);// 模拟耗时操作
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }


}
